#include "../include/linked_list.h"
#include "../include/inner_object.h"

 Node::Node()
 {
 }

Node::Node(hObject ele, Node *next, Node *prev): ele(ele), next(next), prev(prev)
{
}

LinkedList::LinkedList()
{
	release_mem = false;
	head = tail = 0;
	size = 0;
}
	
LinkedList::LinkedList(bool r_m) : release_mem(r_m)
{
	head = tail = 0;
	size = 0;
}
	
void LinkedList::push_back(hObject new_ele)
{
	Node *n = new Node(new_ele, 0, 0);
	if(head == 0 && tail == 0)
	{
		head = tail = n;
	}
	else
	{
		n->prev = tail;
		tail->next = n;
		tail = n;
	}
	size++;
}
	
void LinkedList::pop_back()
{
	if(head == 0 || tail == 0)return;	
	remove(tail);
}
	
int LinkedList::find(hObject ele, Node **node)
{
	int index = -1;
	if(node)*node = 0;
	
	if(head != 0 && tail != 0)
	{
		Node *p = head;
		for(int i = 0; p != 0; i++, p = p->next)
		{
			if(p->ele == ele)
			{
				index = i;
				if(node)*node = p;
				break;
			}
		}
	}
	return index;
}
	
void LinkedList::remove(Node *n)
{
	if(n == 0 || head == 0 || tail == 0)return;
	if(n == head && n == tail)head = tail = 0;
	else	if(n == head)
	{
		head = n->next;
		head->prev = 0;
	}
	else	if(n == tail)
	{
		tail = n->prev;
		tail->next = 0;
	}
	else
	{
		n->prev->next = n->next;
		n->next->prev = n->prev;
	}
	if(release_mem)delete (InnerObject *)((n->ele) >> 32);
	delete n;
	size--;
}

void LinkedList::remove(hObject ele)
{
	Node *n = 0;
	find(ele, &n);
	if(n)remove(n);
}

Node *LinkedList::getFirst()
{
	return head;
}
	
Node *LinkedList::getLast()
{
	return tail;
}

Node *LinkedList::getNext(Node *cur)
{
	return cur->next;
}

Node *LinkedList::getPrev(Node *cur)
{
	return cur->prev;
}

int LinkedList::getSize()
{
	return size;
}

void LinkedList::clear()
{
	Node *p = head, *next;
	while(p != 0)
	{
		next = p->next;
		remove(p);
		p = next;
	}
}

LinkedList::~LinkedList()
{
	Node *p = head, *next;
	while(p != 0)
	{
		next = p->next;
		if(release_mem)delete (InnerObject *)(p->ele >> 32);
		delete p;
		p = next;
	}
}